package com.jiumi.api.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baidubce.http.ApiExplorerClient;
import com.baidubce.http.AppSigner;
import com.baidubce.http.HttpMethodName;
import com.baidubce.model.ApiExplorerRequest;
import com.baidubce.model.ApiExplorerResponse;
import com.jiumi.api.entity.IDCardDo;
import com.jiumi.api.util.CheckCertUtil;
import com.jiumi.baseconfig.domain.BaseCityInfo;
import com.jiumi.baseconfig.domain.BaseUser;
import com.jiumi.baseconfig.domain.BaseUserResume;
import com.jiumi.baseconfig.service.IBaseCityInfoService;
import com.jiumi.baseconfig.service.IBaseUserResumeService;
import com.jiumi.baseconfig.service.IBaseUserService;
import com.jiumi.common.config.AliConfig;
import com.jiumi.common.core.redis.RedisCache;
import com.jiumi.util.Base64Util;
import com.jiumi.util.BirthUtils;
import com.jiumi.util.FileUtil;
import com.jiumi.common.config.JiumiConfig;
import com.jiumi.common.core.domain.AjaxResult;
import com.jiumi.common.exception.file.InvalidExtensionException;
import com.jiumi.common.utils.DateUtils;
import com.jiumi.common.utils.StringUtils;
import com.jiumi.common.utils.file.FileUploadUtils;
import com.jiumi.config.BaiDuApiConfig;
import com.jiumi.util.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 百度API接口
 *
 * @author zl
 */
@RestController
@RequestMapping("/api/noAuth")
@Slf4j
public class BaiDuApiController {


    @Autowired
    private BaiDuApiConfig baiDuApiConfig;

    @Autowired
    private IBaseCityInfoService baseCityInfoService;

    @Autowired
    private IBaseUserService userInfoService;

    @Autowired
    private RedisCache redisCache;


    private static String[] allowed = new String[]{"jpg", "jpeg", "png", "bmp"};


    @PostMapping(value = "/ocrIdCard", produces = "application/json;charset=UTF-8")
    public AjaxResult ocrIdCard(@RequestParam("file")MultipartFile file ,@RequestParam("cardSide") String cardSide){
        if (StringUtils.isNull(file)) {
            return AjaxResult.error("文件不能为空");
        }
        String fileName = file.getOriginalFilename();
        final boolean b = this.checkFile(fileName);
        if (!b) {
            return AjaxResult.error("文件格式不支持");
        }
        long size = file.getSize();
        long maxSize =10 * 1024 * 1024; //最大5M
        if (size > maxSize) {
            return AjaxResult.error("图片最大为10M");
        }
        String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard";
        String errorMsg = "";
        String filePath = "";
        try {
            filePath = FileUploadUtils.uploadToLocal(JiumiConfig.getUploadPath(), file, allowed);

            byte[] imgData = FileUtil.readFileByBytes(filePath);
            String imgStr = Base64Util.encode(imgData);
            String imgParam = URLEncoder.encode(imgStr, "UTF-8");

            String param = "id_card_side=" + cardSide + "&image=" + imgParam;

            // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。
            String accessToken = this.getAccessToken();
            String result = HttpUtil.post(url, accessToken, param);

            String str = StrUtil.str(result.getBytes(), "utf-8");

            InputStream inputStream=new FileInputStream(new File(filePath));
            // 上传并返回新文件名称
            FileUploadUtils.uploadToOss(inputStream, fileName);
            String certUrl =  AliConfig.getImgPrefix() + fileName;
            JSONObject parse = (JSONObject) JSON.parse(str);
            JSONObject wordResult=parse.getJSONObject("words_result");
            IDCardDo cardInfo=new IDCardDo();

            if("front".equals(cardSide)) {
                JSONObject authName = wordResult.getJSONObject("姓名");
                JSONObject nation = wordResult.getJSONObject("民族");
                JSONObject address = wordResult.getJSONObject("住址");
                JSONObject certcode = wordResult.getJSONObject("公民身份号码");
                JSONObject birthDay = wordResult.getJSONObject("出生");
                String birthStr = birthDay.getString("words");
                JSONObject sex = wordResult.getJSONObject("性别");

                cardInfo.setAuthName(authName.getString("words"));
                cardInfo.setNation(nation.getString("words"));
                cardInfo.setAddress(address.getString("words"));
                cardInfo.setCertCode(certcode.getString("words"));
                String province=cardInfo.getCertCode().substring(0,2)+"0000";
                BaseCityInfo city1= baseCityInfoService.selectBaseCityInfoByCode(province);
                String city=cardInfo.getCertCode().substring(0,4)+"00";
                cardInfo.setNativePlace("");
                if(city1!=null){
                    cardInfo.setNativePlace(city1.getValue());
                }
                BaseCityInfo city2= baseCityInfoService.selectBaseCityInfoByCode(city);
                if(city2!=null) {
                    cardInfo.setNativePlace(cardInfo.getNativePlace()+city2.getValue());
                }
                cardInfo.setBirthDate(DateUtils.dateTime("yyyyMMdd", birthStr));
                cardInfo.setSex(sex.getString("words"));
                String constellation = BirthUtils.getConstellation(cardInfo.getBirthDate());
                cardInfo.setConstellation(constellation);
                String zodiac = BirthUtils.getZodiac(Integer.parseInt(birthStr.substring(0, 4)));
                cardInfo.setZodiac(zodiac);
                cardInfo.setCertImage1(certUrl);

                JSONObject checkResult= CheckCertUtil.testCertCode(cardInfo.getAuthName(),cardInfo.getCertCode());
                if(!checkResult.getBoolean("isok")){
                    return AjaxResult.error("身份证验证失败，原因："+checkResult.getString("error"));
                }else{
                    log.info("身份证验证结果"+checkResult.getString("msg"));
                }
            }
            else if("back".equals(cardSide)) {
                JSONObject endDate = wordResult.getJSONObject("失效日期");
                cardInfo.setCertEndDate(endDate.getString("words"));
                //JSONObject city = wordResult.getJSONObject("签发机关");
                //cardInfo.setNativePlace(city.getString("words"));
                cardInfo.setCertImage2(certUrl);
            }
            else{
                return AjaxResult.error("参数传递错误");
            }
            return AjaxResult.success("操作成功", cardInfo);
        } catch (IOException | InvalidExtensionException e) {
            errorMsg = e.getMessage();
        } catch (Exception e) {
            log.error("识别错误,{}", e.getMessage());
            errorMsg = e.getMessage();
            e.printStackTrace();
        } finally {
            File f = new File(filePath);
            if (f.exists()) {
                f.delete();
            }
        }
        return AjaxResult.error(errorMsg);
    }

    @PostMapping(value = "/checkCertCode", produces = "application/json;charset=UTF-8")
    public AjaxResult checkCertCode(@RequestParam("file")MultipartFile file,@RequestParam(value="orderCode",required = false)String orderCode ){
        if (StringUtils.isNull(file)) {
            return AjaxResult.error("文件不能为空");
        }
        String fileName = file.getOriginalFilename();
        final boolean b = this.checkFile(fileName);
        if (!b) {
            return AjaxResult.error("文件格式不支持");
        }
        long size = file.getSize();
        long maxSize =10 * 1024 * 1024; //最大5M
        if (size > maxSize) {
            return AjaxResult.error("图片最大为10M");
        }
        String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard";
        String errorMsg = "";
        String filePath = "";
        String userKey="orderCode-"+orderCode;
        try {
            filePath = FileUploadUtils.uploadToLocal(JiumiConfig.getUploadPath(), file, allowed);

            byte[] imgData = FileUtil.readFileByBytes(filePath);
            String imgStr = Base64Util.encode(imgData);
            String imgParam = URLEncoder.encode(imgStr, "UTF-8");

            String param = "id_card_side=front&image=" + imgParam;

            // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。
            String accessToken = this.getAccessToken();
            String result = HttpUtil.post(url, accessToken, param);

            String str = StrUtil.str(result.getBytes(), "utf-8");

            InputStream inputStream=new FileInputStream(new File(filePath));
            // 上传并返回新文件名称
            FileUploadUtils.uploadToOss(inputStream, fileName);
            String certUrl =  AliConfig.getImgPrefix() + fileName;
            JSONObject parse = (JSONObject) JSON.parse(str);
            JSONObject wordResult=parse.getJSONObject("words_result");

            JSONObject certcode = wordResult.getJSONObject("公民身份号码");
            JSONObject nation = wordResult.getJSONObject("民族");
            if(certcode==null){
                return AjaxResult.error("身份证识别失败，请选择清晰的身份证照片");
            }
            String certCode=certcode.getString("words");
            if(StringUtils.isEmpty(certCode)){
                return AjaxResult.error("身份证识别失败，请选择清晰的身份证照片");
            }

            JSONObject authName = wordResult.getJSONObject("姓名");
            String name=authName.getString("words");
            JSONObject checkResult= CheckCertUtil.testCertCode(name,certCode);

            if(checkResult.getBoolean("isok")){
                AjaxResult dataResult= AjaxResult.success("操作成功");
                JSONObject idResult=checkResult.getJSONObject("IdCardInfor");
                dataResult.put("authName",name);
                dataResult.put("certCode",certCode);
                dataResult.put("nation",nation.getString("words"));
                dataResult.put("address",idResult.getString("area"));
                redisCache.setCacheObject(userKey,"Y",1, TimeUnit.DAYS);
                return dataResult;
            }else{
                redisCache.setCacheObject(userKey,"Y",1, TimeUnit.DAYS);
                return AjaxResult.error("验证失败，身份证、姓名 不正确");
            }
        } catch (IOException | InvalidExtensionException e) {
            redisCache.setCacheObject(userKey,"Y",1, TimeUnit.DAYS);
            errorMsg = e.getMessage();
        } catch (Exception e) {
            redisCache.setCacheObject(userKey,"Y",1, TimeUnit.DAYS);
            log.error("识别错误,{}", e.getMessage());
            errorMsg = e.getMessage();
            e.printStackTrace();
        } finally {
            File f = new File(filePath);
            if (f.exists()) {
                f.delete();
            }
        }
        return AjaxResult.error(errorMsg);
    }




    /**
     * 行驶证识别
     *
     * @return
     */
    @PostMapping(value = "/ocrVehicleLicense", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public AjaxResult vehicleLicense(@RequestParam("file") MultipartFile file) {
        if (StringUtils.isNull(file)) {
            return AjaxResult.error("文件不能为空");
        }
        String fileName = file.getOriginalFilename();
        final boolean b = this.checkFile(fileName);
        if (!b) {
            return AjaxResult.error("文件格式不支持");
        }
        long size = file.getSize();
        long maxSize = 10 * 1024 * 1024; //最大5M
        if (size > maxSize) {
            return AjaxResult.error("图片最大为10M");
        }
        fileName = UUID.randomUUID() + fileName;
        // 请求url
        String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/vehicle_license";
        String errorMsg = "";
        String filePath = "";
        try {
            filePath = FileUploadUtils.uploadToLocal(JiumiConfig.getUploadPath(), file, allowed);

            byte[] imgData = FileUtil.readFileByBytes(filePath);
            String imgStr = Base64Util.encode(imgData);
            String imgParam = URLEncoder.encode(imgStr, "UTF-8");

            String param = "image=" + imgParam;
            // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。
            String accessToken = this.getAccessToken();
            String result = HttpUtil.post(url, accessToken, param);

            String str = StrUtil.str(result.getBytes(), "utf-8");
            JSONObject parse = (JSONObject) JSON.parse(str);
            JSONObject words_result = (JSONObject) parse.get("words_result");
            JSONObject fObject = (JSONObject)words_result.get("发证日期");
            JSONObject zObject = (JSONObject)words_result.get("注册日期");
            if(StringUtils.isNull(zObject)){
                zObject = (JSONObject)words_result.get("注册登记日期");
            }
            if(StringUtils.isNotNull(fObject)) {
                String f_date = (String) Optional.ofNullable(fObject.get("words")).orElse("");

                fObject.put("words",parseDate(f_date));
                words_result.put("发证日期",fObject);
            }

            if(StringUtils.isNotNull(zObject)) {
                String z_date = (String) Optional.ofNullable(zObject.get("words")).orElse("");
                zObject.put("words",parseDate(z_date));
                words_result.put("注册日期", zObject);
            }
            parse.put("words_result",words_result);
            return AjaxResult.success("操作成功", parse);
        } catch (IOException e) {
            errorMsg = e.getMessage();
        } catch (InvalidExtensionException e) {
            errorMsg = e.getMessage();
        } catch (Exception e) {
            log.error("识别错误,{}", e.getMessage());
            errorMsg = e.getMessage();
        } finally {
            File f = new File(filePath);
            if (f.exists()) {
                f.delete();
            }
        }
        return AjaxResult.error(errorMsg);
    }

    private boolean checkFile(String fileName) {
        if (StringUtils.isEmpty(fileName)) {
            return false;
        }
        final String[] split = fileName.split("\\.");
        if (split.length < 2) {
            return false;
        }
        for (String s : allowed) {
            if (split[split.length - 1].equalsIgnoreCase(s)) {
                return true;
            }
        }
        return false;
    }


    private String getAccessToken() {
        String getAccessTokenUrl = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=" + baiDuApiConfig.getApiKey() + "&client_secret=" + baiDuApiConfig.getSecretKey() + "&";
        try {
            URL realUrl = new URL(getAccessTokenUrl);
            // 打开和URL之间的连接
            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
//            for (String key : map.keySet()) {
//                System.err.println(key + "--->" + map.get(key));
//            }
            // 定义 BufferedReader输入流来读取URL的响应
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String result = "";
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            /**
             * 返回结果示例
             */
            JSONObject jsonObject = JSONObject.parseObject(result);
            String access_token = jsonObject.getString("access_token");
            return access_token;
        } catch (Exception e) {
            log.error("获取token失败！{}", e.getMessage());
        }
        return "";
    }

    public static String parseDate(String s) {
        if (StringUtils.isEmpty(s)) {
            return null;
        }
        Date date = DateUtils.parseDate(s);
        String s1 = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, date);
        return s1;
    }

    public JSONObject checkIdCard11111111(String name,String idCardNo) {
        String path = "https://jumssread.api.bdymkt.com/idcard/validate";
        ApiExplorerRequest request = new ApiExplorerRequest(HttpMethodName.POST, path);
        request.setCredentials("28f6eb693f714d6bac4cae0988d4d5b0", "ffbddfedd42141898d3fe9a56e12372a");

        request.addHeaderParameter("Content-Type", "application/x-www-form-urlencoded");

        request.addQueryParameter("name", name);
        request.addQueryParameter("idCardNo", idCardNo);



        ApiExplorerClient client = new ApiExplorerClient(new AppSigner());
        ApiExplorerResponse response=null;
        JSONObject obj=null;
        try {
            response = client.sendRequest(request);
            log.info("身份证验证结果："+response.getResult());
            // 返回结果格式为Json字符串
            obj=JSONObject.parseObject(response.getResult());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }


}
